Snippets Collections
<?php
// Add Re-Order submenu to each post type
function add_reorder_submenu() {
    $post_types = get_post_types(array('show_ui' => true), 'objects');
    foreach ($post_types as $post_type) {
        // Skip the attachment post type
        if ($post_type->name === 'attachment') {
            continue;
        }
        $parent_slug = ($post_type->name === 'post') ? 'edit.php' : 'edit.php?post_type=' . $post_type->name;
        add_submenu_page(
            $parent_slug,
            'Re-Order ' . $post_type->label,
            'Re-Order',
            'edit_posts',
            $post_type->name . '-reorder',
            'display_reorder_page'
        );
    }
}
add_action('admin_menu', 'add_reorder_submenu');

// Display the reorder page
function display_reorder_page() {
    if (!current_user_can('edit_posts')) {
        wp_die(__('You do not have sufficient permissions to access this page.'));
    }

    $current_screen = get_current_screen();
    $post_type = $current_screen->post_type;
    if (empty($post_type)) {
        $post_type = sanitize_text_field($_GET['post_type'] ?? 'post');
    }
    $post_type_object = get_post_type_object($post_type);

    if (!$post_type_object || $post_type === 'attachment') {
        wp_die(__('Invalid post type.'));
    }

    $query_args = array(
        'post_type' => $post_type,
        'post_status' => array('publish', 'draft', 'pending', 'future', 'private'),
        'posts_per_page' => -1,
        'orderby' => 'menu_order',
        'order' => 'ASC',
        'suppress_filters' => true,
    );
    $posts = get_posts($query_args);

    $total_items = count($posts);

    ?>
    <div class="wrap">
        <h1><?php echo esc_html(sprintf('Re-Order %s', $post_type_object->labels->name)); ?></h1>
        
        <div id="message" class="updated notice is-dismissible" style="display:none;"><p></p></div>
        
        <p><?php esc_html_e('Drag and drop items to reorder them. Click "Update Order" to save changes.'); ?></p>
        <button id="update-order" class="button button-primary"><?php esc_html_e('Update Order'); ?></button>
        <button id="reset-order" class="button"><?php esc_html_e('Reset Order'); ?></button>
        
        <p class="item-count"><?php esc_html_e('Total items:'); ?> <span id="total-items"><?php echo esc_html($total_items); ?></span></p>
        
 <ul id="sortable-list" class="widefat striped">
        <?php foreach ($posts as $post) : 
            $title = $post->post_title;
            $status = get_post_status($post->ID);
            $status_class = ($status !== 'publish') ? sprintf(' post-status-%s', sanitize_html_class($status)) : '';
        ?>
            <li class="ui-state-default<?php echo esc_attr($status_class); ?>" data-id="<?php echo esc_attr($post->ID); ?>">
                <span class="dashicons dashicons-menu"></span>
                <?php echo esc_html($title); ?>
                <span class="post-status">(<?php echo esc_html($status); ?>)</span>
            </li>
        <?php endforeach; ?>
        </ul>

        <p class="reorder-footer">
            <?php
            echo wp_kses(
                sprintf(
                    'Created by <a href="%s" target="_blank">Yasir Shabbir</a>',
                    'https://yasirshabbir.com'
                ),
                array(
                    'a' => array(
                        'href' => array(),
                        'target' => array()
                    )
                )
            );
            ?>
        </p>
    </div>

    <style>
        #sortable-list { list-style-type: none; margin: 20px 0; padding: 0; }
        #sortable-list li { 
            padding: 10px 15px !important; 
            background: #fff; 
            border: 1px solid #ddd; 
            margin-bottom: 5px; 
            cursor: move; 
            font-size: 14px !important;
            line-height: 1.4;
        }
        #sortable-list li:hover { background: #f9f9f9; }
        #sortable-list .dashicons { 
            color: #bbb; 
            margin-right: 10px;
            font-size: 20px;
            line-height: 1;
        }
        .ui-sortable-helper { 
            background: #f9f9f9 !important; 
            box-shadow: 0 2px 5px rgba(0,0,0,0.15); 
        }
        #update-order, #reset-order { display: inline-block; margin-right: 10px; margin-bottom: 20px; }
        .updating { opacity: 0.5; pointer-events: none; }
        .post-status { font-size: 0.8em; color: #666; margin-left: 5px; }
        .post-status-draft { opacity: 0.7; }
        .post-status-pending { background-color: #fef7f1; }
        .post-status-future { background-color: #f1fef7; }
        .post-status-private { background-color: #fef1f1; }
        .item-count { margin-top: 10px; font-weight: bold; }
        
             .reorder-footer {
            margin-top: 20px;
            text-align: center;
            font-style: italic;
            color: #666;
        }
    </style>

    <script>
    jQuery(document).ready(function($) {
        $("#sortable-list").sortable({
            handle: ".dashicons-menu"
        });

        function updateOrder(action, buttonId) {
            var $button = $("#" + buttonId);
            var $list = $("#sortable-list");
            var order = $list.sortable("toArray", {attribute: "data-id"});
            
            $button.addClass("updating").text(action === "update_post_order" ? "<?php esc_html_e('Updating...'); ?>" : "<?php esc_html_e('Resetting...'); ?>");
            $list.addClass("updating");
            
            $.ajax({
                url: ajaxurl,
                type: "POST",
                data: {
                    action: action,
                    order: order,
                    post_type: <?php echo wp_json_encode($post_type); ?>,
                    security: <?php echo wp_json_encode(wp_create_nonce('post_order_nonce')); ?>
                },
                success: function(response) {
                    if (response.success) {
                        $("#message").html("<p>" + response.data + "</p>").show();
                        if (action === "reset_post_order") {
                            location.reload();
                        }
                    } else {
                        $("#message").html("<p><?php esc_html_e('Error:'); ?> " + response.data + "</p>").show();
                    }
                },
                error: function() {
                    $("#message").html("<p><?php esc_html_e('An error occurred.'); ?></p>").show();
                },
                complete: function() {
                    $button.removeClass("updating").text(action === "update_post_order" ? "<?php esc_html_e('Update Order'); ?>" : "<?php esc_html_e('Reset Order'); ?>");
                    $list.removeClass("updating");
                }
            });
        }

        function updateItemCount() {
            var count = $("#sortable-list li").length;
            $("#total-items").text(count);
        }

        $("#update-order").click(function() {
            updateOrder("update_post_order", "update-order");
        });

        $("#reset-order").click(function() {
            if (confirm("<?php esc_html_e('Are you sure you want to reset the order? This cannot be undone.'); ?>")) {
                updateOrder("reset_post_order", "reset-order");
                setTimeout(updateItemCount, 500);
            }
        });

        updateItemCount();

        $("#sortable-list").on("DOMSubtreeModified", function() {
            updateItemCount();
        });
    });
    </script>
    <?php
}

// AJAX handler to update post order
function update_post_order() {
    check_ajax_referer('post_order_nonce', 'security');
    
    $order = $_POST['order'];
    $post_type = $_POST['post_type'];
    
    if ($post_type === 'attachment') {
        wp_send_json_error('Reordering media items is not supported.');
        return;
    }
    
    foreach ($order as $menu_order => $post_id) {
        wp_update_post(array(
            'ID' => intval($post_id),
            'menu_order' => intval($menu_order)
        ));
    }
    
    wp_send_json_success('Order updated successfully');
}
add_action('wp_ajax_update_post_order', 'update_post_order');

// AJAX handler to reset post order
function reset_post_order() {
    check_ajax_referer('post_order_nonce', 'security');
    
    $post_type = $_POST['post_type'];
    
    if ($post_type === 'attachment') {
        wp_send_json_error('Reordering media items is not supported.');
        return;
    }
    
    $posts = get_posts(array(
        'post_type' => $post_type,
        'posts_per_page' => -1,
        'post_status' => 'any',
    ));
    
    foreach ($posts as $post) {
        wp_update_post(array(
            'ID' => $post->ID,
            'menu_order' => 0
        ));
    }
    
    wp_send_json_success('Order reset successfully');
}
add_action('wp_ajax_reset_post_order', 'reset_post_order');

// Update post order when posts are created or trashed
function set_default_post_order($post_id, $post, $update) {
    if (!$update && $post->post_type !== 'attachment') {
        $post_type = get_post_type($post_id);
        $last_post = get_posts(array(
            'post_type' => $post_type,
            'posts_per_page' => 1,
            'orderby' => 'menu_order',
            'order' => 'DESC'
        ));
        $new_menu_order = (!empty($last_post)) ? $last_post[0]->menu_order + 1 : 0;
        wp_update_post(array(
            'ID' => $post_id,
            'menu_order' => $new_menu_order
        ));
    }
}
add_action('wp_insert_post', 'set_default_post_order', 10, 3);

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension